home *** CD-ROM | disk | FTP | other *** search
/ Practical Internet 2002 February / Practical Internet February 2002.iso / pc / Software / Browsing / httrack-3.09e2.exe / {app} / src / htscache.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-07  |  27.7 KB  |  868 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       cache system (index and stores files in cache)         */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htscache.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htsbasenet.h"
  43. #include "htsmd5.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. /* END specific definitions */
  48.  
  49. #undef test_flush
  50. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  51.  
  52. // routines de mise en cache
  53.  
  54. /*
  55.   VERSION 1.0 :
  56.   -----------
  57.  
  58. .ndx file
  59.  file with data
  60.    <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links
  61.  file without data
  62.    <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links
  63.  
  64. .dat file
  65.  [ file ] * 
  66. with
  67.   file= (with data)
  68.    [ bytes ] * sizeof(htsblk header) [ bytes ] * n(length of file given in htsblk header)
  69.  file= (without data)
  70.    [ bytes ] * sizeof(htsblk header)
  71. with
  72.  <string>(name) = <length in ascii>+<lf>+<data>
  73.  
  74.  
  75.   VERSION 1.1/1.2 :
  76.   ---------------
  77.  
  78. .ndx file
  79.  file with data
  80.    <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links
  81.  file without data
  82.    <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links
  83.  
  84. .dat file
  85.    <string>("CACHE-1.1") [ [Header_1.1] [bytes] * n(length of file given in header) ] *
  86. with
  87.  Header_1.1=
  88.    <int>(statuscode)
  89.    <int>(size)
  90.    <string>(msg)
  91.    <string>(contenttype)
  92.    <string>(last-modified)
  93.    <string>(Etag)
  94.    [<string>"SD" <string>(supplemental data)]
  95.    [<string>"SD" <string>(supplemental data)]
  96.    ...
  97.    <string>"HTS" (end of header)
  98.    <int>(number of bytes of data) (0 if no data written)
  99. */
  100.  
  101. // Nouveau: si != text/html ne stocke que la taille
  102.  
  103.  
  104. void cache_mayadd(httrackp* opt,cache_back* cache,htsblk* r,char* url_adr,char* url_fil,char* url_save) {
  105.   if ((opt->debug>0) && (opt->log!=NULL)) {
  106.     fspc(opt->log,"debug"); fprintf(opt->log,"File checked by cache: %s"LF,url_adr);
  107.   }            
  108.   // ---stockage en cache---
  109.   // stocker dans le cache?
  110.   if (opt->cache) {
  111.     if (cache->dat!=NULL) {
  112.       // c'est le seul endroit ou l'on ajoute des elements dans le cache (fichier entier ou header)
  113.       // on stocke tout fichier "ok", mais Θgalement les rΘponses 404,301,302...
  114.       if ((r->statuscode==200)         /* stocker rΘponse standard, plus */
  115.         || (r->statuscode==204)     /* no content */
  116.         || (r->statuscode==301)     /* moved perm */
  117.         || (r->statuscode==302)     /* moved temp */
  118.         || (r->statuscode==303)     /* moved temp */
  119.         || (r->statuscode==307)     /* moved temp */
  120.         || (r->statuscode==401)     /* authorization */
  121.         || (r->statuscode==403)     /* unauthorized */
  122.         || (r->statuscode==404)     /* not found */
  123.         || (r->statuscode==410)     /* gone */
  124.         )
  125.       {        /* ne pas stocker si la page gΘnΘrΘe est une erreur */
  126.         if (!r->is_file) {
  127.           // stocker fichiers (et robots.txt)
  128.           if ( (strnotempty(url_save)) || (strcmp(url_fil,"/robots.txt")==0)) {
  129.             // ajouter le fichier au cache
  130.             cache_add(*r,url_adr,url_fil,url_save,cache->ndx,cache->dat,opt->all_in_cache);
  131.           }
  132.         }
  133.       }
  134.     }
  135.   }
  136.   // ---fin stockage en cache---
  137. }
  138.  
  139.  
  140. /* Ajout d'un fichier en cache */
  141. void cache_add(htsblk r,char* url_adr,char* url_fil,char* url_save,FILE* cache_ndx,FILE* cache_dat,int all_in_cache) {
  142.   int pos;
  143.   char s[256];
  144.   char buff[HTS_URLMAXSIZE*4];
  145.   int ok=1;
  146.   int dataincache=0;    // donnΘe en cache?
  147.   /*char digest[32+2];*/
  148.   /*digest[0]='\0';*/
  149.  
  150.   // Longueur url_save==0?
  151.   if ( (strnotempty(url_save)==0) ) {
  152.     if (strcmp(url_fil,"/robots.txt")==0)        // robots.txt
  153.       dataincache=1;
  154.     else
  155.       return;   // erreur (sauf robots.txt)
  156.   }
  157.  
  158.   if (r.size <= 0)   // taille <= 0 
  159.     return;          // refusΘ..
  160.  
  161.   // Mettre les *donΘes* en cache ?
  162.   if (is_hypertext_mime(r.contenttype))    // html, mise en cache des donnΘes et 
  163.     dataincache=1;                               // pas uniquement de l'en tΩte
  164.   else if (all_in_cache)
  165.     dataincache=1;                               // forcer tout en cache
  166.  
  167.   /* calcul md5 ? */
  168.   /*
  169.   if (is_hypertext_mime(r.contenttype)) {    // html, calcul MD5
  170.     if (r.adr) {
  171.       domd5mem(r.adr,r.size,digest,1,0);
  172.     }
  173.   }*/
  174.  
  175.   // Position
  176.   fflush(cache_dat); fflush(cache_ndx);
  177.   pos=ftell(cache_dat);
  178.   // Θcrire pointeur seek, adresse, fichier
  179.   if (dataincache)   // patcher
  180.     sprintf(s,"%d\n",pos);    // ecrire tel que (eh oui Θvite les \0..)
  181.   else
  182.     sprintf(s,"%d\n",-pos);   // ecrire tel que (eh oui Θvite les \0..)
  183.  
  184.   // data
  185.   // Θcrire donnΘes en-tΩte, donnΘes fichier
  186.   /*if (!dataincache) {   // patcher
  187.     r.size=-r.size;  // nΘgatif
  188.   }*/
  189.  
  190.   // Construction header
  191.   ok=0;
  192.   if (cache_wint(cache_dat,r.statuscode)!=-1)       // statuscode
  193.   if (cache_wLLint(cache_dat,r.size)!=-1)           // size
  194.   if (cache_wstr(cache_dat,r.msg)!=-1)              // msg
  195.   if (cache_wstr(cache_dat,r.contenttype)!=-1)      // contenttype
  196.   if (cache_wstr(cache_dat,r.lastmodified)!=-1)     // last-modified
  197.   if (cache_wstr(cache_dat,r.etag)!=-1)             // Etag
  198.   if (cache_wstr(cache_dat,(r.location!=NULL)?r.location:"")!=-1)         // 'location' pour moved
  199.   if (cache_wstr(cache_dat,r.cdispo)!=-1)           // Content-disposition
  200.   if (cache_wstr(cache_dat,"HTS")!=-1)              // end of header
  201.     ok=1;       /* ok */
  202.   // Fin construction header
  203.  
  204.   /*if ((int) fwrite((char*) &r,1,sizeof(htsblk),cache_dat) == sizeof(htsblk)) {*/
  205.   if (ok) {
  206.     if (dataincache) {    // mise en cache?
  207.       if (!r.adr) {       /* taille nulle (parfois en cas de 301 */
  208.         if (cache_wLLint(cache_dat,0)==-1)          /* 0 bytes */
  209.           ok=0;
  210.       } else if (r.is_write==0) {  // en mΘmoire, recopie directe
  211.         if (cache_wLLint(cache_dat,r.size)!=-1) {
  212.           if (r.size>0) {   // taille>0
  213.             if ((INTsys) fwrite(r.adr,1,(INTsys)r.size,cache_dat)!=r.size)
  214.               ok=0;
  215.           } else    // taille=0, ne rien Θcrire
  216.             ok=0;
  217.         } else
  218.           ok=0;
  219.       } else {  // recopier fichier dans cache
  220.         FILE* fp;
  221.         // On recopie le fichier..
  222.         LLint file_size=fsize(fconv(url_save));
  223.         if (file_size>=0) {
  224.           if (cache_wLLint(cache_dat,file_size)!=-1) {
  225.             fp=fopen(fconv(url_save),"rb");
  226.             if (fp!=NULL) {
  227.               char buff[32768];
  228.               int nl;
  229.               do {
  230.                 nl=fread(buff,1,32768,fp);
  231.                 if (nl>0) { 
  232.                   if ((INTsys) fwrite(buff,1,(INTsys)nl,cache_dat)!=nl) {  // erreur
  233.                     nl=-1;
  234.                     ok=0;
  235.                   }
  236.                 }
  237.               } while(nl>0);
  238.               fclose(fp);
  239.             } else ok=0;
  240.           } else ok=0;
  241.         } else ok=0;
  242.       }
  243.     } else {
  244.       if (cache_wLLint(cache_dat,0)==-1)          /* 0 bytes */
  245.         ok=0;
  246.     }
  247.   } else ok=0;
  248.   /*if (!dataincache) {   // dΘpatcher
  249.     r.size=-r.size;
  250.   }*/
  251.  
  252.   // index
  253.   // adresse+cr+fichier+cr
  254.   if (ok) {
  255.     buff[0]='\0'; strcat(buff,url_adr); strcat(buff,"\n"); strcat(buff,url_fil); strcat(buff,"\n");
  256.     cache_wstr(cache_ndx,buff);
  257.     fwrite(s,1,strlen(s),cache_ndx);
  258.   }  // si ok=0 on a peut Ωtre Θcrit des donnΘes pour rien mais on s'en tape
  259.   
  260.   // en cas de plantage, on aura au moins le cache!
  261.   fflush(cache_dat); fflush(cache_ndx);
  262. }
  263.  
  264.  
  265. // lecture d'un fichier dans le cache
  266. // si save==null alors test unqiquement
  267. htsblk cache_read(httrackp* opt,cache_back* cache,char* adr,char* fil,char* save) {
  268. #if HTS_FAST_CACHE
  269.   long int hash_pos;
  270.   int hash_pos_return;
  271. #else
  272.   char* a;
  273. #endif
  274.   char buff[HTS_URLMAXSIZE*2];
  275.   static char location[HTS_URLMAXSIZE*2];
  276.   htsblk r;
  277.   int ok=0;
  278.   int header_only=0;
  279.  
  280.   bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET; strcpy(location,""); r.location=location;
  281. #if HTS_FAST_CACHE
  282.   strcpy(buff,adr); strcat(buff,fil);
  283.   hash_pos_return=inthash_read((inthash)cache->hashtable,buff,(long int*)&hash_pos);
  284. #else
  285.   buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n");
  286.   if (cache->use)
  287.     a=strstr(cache->use,buff);
  288.   else
  289.     a=NULL;       // forcer erreur
  290. #endif
  291.  
  292.   // en cas de succΦs
  293. #if HTS_FAST_CACHE
  294.   if (hash_pos_return) {
  295. #else
  296.   if (a!=NULL) {  // OK existe en cache!
  297. #endif
  298.     int pos;
  299. #if DEBUGCA
  300.     fprintf(stdout,"..cache: %s%s at ",adr,fil);
  301. #endif
  302.     
  303. #if HTS_FAST_CACHE
  304.     pos=hash_pos;     /* simply */
  305. #else
  306.     a+=strlen(buff);
  307.     sscanf(a,"%d",&pos);    // lire position
  308. #endif
  309. #if DEBUGCA
  310.     printf("%d\n",pos);
  311. #endif
  312.  
  313.     fflush(cache->olddat); 
  314.     if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) {
  315.       /* Importer cache1.0 */
  316.       if (cache->version==0) {
  317.         OLD_htsblk old_r;
  318.         if (fread((char*) &old_r,1,sizeof(old_r),cache->olddat)==sizeof(old_r)) { // lire tout (y compris statuscode etc)
  319.           r.statuscode=old_r.statuscode;
  320.           r.size=old_r.size;        // taille fichier
  321.           strcpy(r.msg,old_r.msg);
  322.           strcpy(r.contenttype,old_r.contenttype);
  323.           ok=1;     /* import  ok */
  324.         }
  325.       /* */
  326.       /* Cache 1.1 */
  327.       } else {
  328.         char check[256];
  329.         LLint size_read;
  330.         check[0]='\0';
  331.         //
  332.         cache_rint(cache->olddat,&r.statuscode);
  333.         cache_rLLint(cache->olddat,&r.size);
  334.         cache_rstr(cache->olddat,r.msg);
  335.         cache_rstr(cache->olddat,r.contenttype);
  336.         cache_rstr(cache->olddat,r.lastmodified);
  337.         cache_rstr(cache->olddat,r.etag);
  338.         cache_rstr(cache->olddat,r.location);
  339.         if (cache->version >= 2)
  340.           cache_rstr(cache->olddat,r.cdispo);
  341.         //
  342.         cache_rstr(cache->olddat,check);
  343.         if (strcmp(check,"HTS")==0) {           /* intΘgritΘ OK */
  344.           ok=1;
  345.         }
  346.         cache_rLLint(cache->olddat,&size_read);       /* lire size pour Ωtre s√r de la taille dΘclarΘe (rΘΘcrire) */
  347.         if (size_read>0) {                         /* si inscrite ici */
  348.           r.size=size_read;
  349.         } else {                              /* pas de donnΘes directement dans le cache, fichier prΘsent? */
  350.           if (r.statuscode!=200)
  351.             header_only=1;          /* que l'en tΩte ici! */
  352.         }
  353.       }
  354.  
  355.       /* Remplir certains champs */
  356.       r.totalsize=r.size;
  357.  
  358.       // lecture du header (y compris le statuscode)
  359.       /*if (fread((char*) &r,1,sizeof(htsblk),cache->olddat)==sizeof(htsblk)) { // lire tout (y compris statuscode etc)*/
  360.       if (ok) {
  361.         // sΘcuritΘ
  362.         r.adr=NULL;
  363.         r.out=NULL;
  364.         ////r.location=NULL;  non, fixΘe lors des 301 ou 302
  365.         r.fp=NULL;
  366.         
  367.         if ( (r.statuscode>=0) && (r.statuscode<=999)
  368.           && (r.notmodified>=0)  && (r.notmodified<=9) ) {   // petite vΘrif intΘgritΘ
  369.           if ((save) && (!header_only) ) {     /* ne pas lire uniquement header */
  370.             //int to_file=0;
  371.             
  372.             r.adr=NULL; r.soc=INVALID_SOCKET; 
  373.             // // r.location=NULL;
  374.             
  375. #if HTS_DIRECTDISK
  376.             // Court-circuit:
  377.             // Peut-on stocker le fichier directement sur disque?
  378.             if ((r.statuscode==200) && (!is_hypertext_mime(r.contenttype)) && (strnotempty(save))) {    // pas HTML, Θcrire sur disk directement
  379.               int ok=0;
  380.               
  381.               r.is_write=1;    // Θcrire
  382.               if (fexist(antislash(save))) {  // un fichier existe dΘja
  383.                 //if (fsize(antislash(save))==r.size) {  // mΩme taille -- NON tant pis (taille mal declaree)
  384.                 ok=1;    // plus rien α faire
  385.                 filenote(save,NULL);        // noter comme connu
  386.                 //}
  387.               }
  388.               
  389.               if ((pos<0) && (!ok)) { // Pas de donnΘe en cache et fichier introuvable : erreur!
  390.                 if (opt->norecatch) {
  391.                   FILE* fp;
  392.                   fp=filecreate(save);
  393.                   if (fp) fclose(fp);
  394.                   //
  395.                   r.statuscode=-1;
  396.                   strcpy(r.msg,"File deleted by user not recaught");
  397.                   ok=1;     // ne pas rΘcupΘrer (et pas d'erreur)
  398.                 } else {
  399.                   r.statuscode=-1;
  400.                   strcpy(r.msg,"Previous cache file not found");
  401.                   ok=1;    // ne pas rΘcupΘrer
  402.                 }
  403.               }
  404.               
  405.               if (!ok) {  
  406.                 r.out=filecreate(save);
  407. #if HDEBUG
  408.                 printf("direct-disk: %s\n",save);
  409. #endif
  410.                 if (r.out!=NULL) {
  411.                   char buff[32768+4];
  412.                   LLint nl;
  413.                   LLint size;
  414.                   size=r.size;
  415.                   do {
  416.                     nl=fread(buff,1,(INTsys) minimum(size,32768),cache->olddat);
  417.                     if (nl>0) {
  418.                       size-=nl; 
  419.                       if ((INTsys) fwrite(buff,1,(INTsys)nl,r.out)!=nl) {  // erreur
  420.                         r.statuscode=-1;
  421.                         strcpy(r.msg,"Cache Read Error : Read To Disk");
  422.                       }
  423.                     }
  424.                   } while((nl>0) && (size>0) && (r.statuscode!=-1));
  425.                   
  426.                   fclose(r.out);
  427.                   r.out=NULL;
  428. #if HTS_WIN==0
  429.                   chmod(save,HTS_ACCESS_FILE);      
  430. #endif          
  431.                   usercommand(0,NULL,antislash(save));
  432.                 } else {
  433.                   r.statuscode=-1;
  434.                   strcpy(r.msg,"Cache Write Error : Unable to Create File");
  435.                   //printf("%s\n",save);
  436.                 }
  437.               }
  438.               
  439.             } else
  440. #endif
  441.             { // lire en mΘmoire
  442.               
  443.               if (pos<0) { // Pas de donnΘe en cache, bizarre car html!!!
  444.                 r.statuscode=-1;
  445.                 strcpy(r.msg,"Previous cache file not found (2)");
  446.               } else {
  447.                 // lire fichier (d'un coup)
  448.                 r.adr=(char*) malloct((INTsys)r.size+4);
  449.                 if (r.adr!=NULL) {
  450.                   if ((INTsys) fread(r.adr,1,(INTsys)r.size,cache->olddat)!=r.size) {  // erreur
  451.                     freet(r.adr);
  452.                     r.adr=NULL;
  453.                     r.statuscode=-1;
  454.                     strcpy(r.msg,"Cache Read Error : Read Data");
  455.                   } else
  456.                     *(r.adr+r.size)='\0';
  457.                   //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  458.                 } else {  // erreur
  459.                   r.statuscode=-1;
  460.                   strcpy(r.msg,"Cache Memory Error");
  461.                 }
  462.               }
  463.             }
  464.           }    // si save==null, ne rien charger (juste en tΩte)
  465.         } else {
  466. #if DEBUGCA
  467.           printf("Cache Read Error : Bad Data");
  468. #endif
  469.           r.statuscode=-1;
  470.           strcpy(r.msg,"Cache Read Error : Bad Data");
  471.         }
  472.       } else {  // erreur
  473. #if DEBUGCA
  474.         printf("Cache Read Error : Read Header");
  475. #endif
  476.         r.statuscode=-1;
  477.         strcpy(r.msg,"Cache Read Error : Read Header");
  478.       }
  479.     } else {
  480. #if DEBUGCA
  481.       printf("Cache Read Error : Seek Failed");
  482. #endif
  483.       r.statuscode=-1;
  484.       strcpy(r.msg,"Cache Read Error : Seek Failed");
  485.     }
  486.   } else {
  487. #if DEBUGCA
  488.     printf("File Cache Not Found");
  489. #endif
  490.     r.statuscode=-1;
  491.     strcpy(r.msg,"File Cache Not Found");
  492.   }
  493.   return r;
  494. }
  495.  
  496. /* write (string1-string2)-data in cache */
  497. /* 0 if failed */
  498. int cache_writedata(FILE* cache_ndx,FILE* cache_dat,char* str1,char* str2,char* outbuff,int len) {
  499.   if (cache_dat) {
  500.     char buff[HTS_URLMAXSIZE*4];
  501.     char s[256];
  502.     int pos;
  503.     fflush(cache_dat); fflush(cache_ndx);
  504.     pos=ftell(cache_dat);
  505.     /* first write data */
  506.     if (cache_wint(cache_dat,len)!=-1) {       // length
  507.       if ((INTsys) fwrite(outbuff,1,(INTsys)len,cache_dat) == (INTsys) len) {   // data
  508.         /* then write index */
  509.         sprintf(s,"%d\n",pos);
  510.         buff[0]='\0'; strcat(buff,str1); strcat(buff,"\n"); strcat(buff,str2); strcat(buff,"\n");
  511.         cache_wstr(cache_ndx,buff);
  512.         if (fwrite(s,1,strlen(s),cache_ndx) == strlen(s)) {
  513.           fflush(cache_dat); fflush(cache_ndx);
  514.           return 1;
  515.         }
  516.       }
  517.     }
  518.   }
  519.   return 0;
  520. }
  521.  
  522. /* read the data corresponding to (string1-string2) in cache */
  523. /* 0 if failed */
  524. int cache_readdata(cache_back* cache,char* str1,char* str2,char** inbuff,int* inlen) {
  525. #if HTS_FAST_CACHE
  526.   if (cache->hashtable) {
  527.     char buff[HTS_URLMAXSIZE*4];
  528.     long int pos;
  529.     strcpy(buff,str1); strcat(buff,str2);
  530.     if (inthash_read((inthash)cache->hashtable,buff,(long int*)&pos)) {
  531.       if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) {
  532.         int len;
  533.         cache_rint(cache->olddat,&len);
  534.         if (len>0) {
  535.           char* mem_buff=(char*)malloct(len+4);    /* Plus byte 0 */
  536.           if (mem_buff) {
  537.             if ((int)fread(mem_buff,1,len,cache->olddat)==len) { // lire tout (y compris statuscode etc)*/
  538.               *inbuff=mem_buff;
  539.               *inlen=len;
  540.               return 1;
  541.             } else
  542.               freet(mem_buff);
  543.           }
  544.         }
  545.       }
  546.     }
  547.   }
  548. #endif
  549.   *inbuff=NULL;
  550.   *inlen=0;
  551.   return 0;
  552. }
  553.  
  554. // renvoyer uniquement en tΩte, ou NULL si erreur
  555. htsblk* cache_header(httrackp* opt,cache_back* cache,char* adr,char* fil) {
  556.   static htsblk r;
  557.   r=cache_read(opt,cache,adr,fil,NULL);              // test uniquement
  558.   if (r.statuscode != -1)
  559.     return &r;
  560.   else
  561.     return NULL;
  562. }
  563.  
  564.           
  565. // Initialisation du cache: crΘer nouveau, renomer ancien, charger..
  566. void cache_init(cache_back* cache,httrackp* opt) {
  567.   // ---
  568.   // utilisation du cache: renommer ancien Θventuel et charger index
  569.   if (opt->cache) {
  570. #if DEBUGCA
  571.     printf("cache init: ");
  572. #endif
  573. #if HTS_WIN
  574.     mkdir(fconcat(opt->path_log,"hts-cache"));
  575. #else
  576.     mkdir(fconcat(opt->path_log,"hts-cache"),HTS_PROTECT_FOLDER);
  577. #endif
  578.     if ((fexist(fconcat(opt->path_log,"hts-cache/new.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  579. #if DEBUGCA
  580.       printf("work with former cache\n");
  581. #endif
  582.       if (fexist(fconcat(opt->path_log,"hts-cache/old.dat")))
  583.         remove(fconcat(opt->path_log,"hts-cache/old.dat"));
  584.       if (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))
  585.         remove(fconcat(opt->path_log,"hts-cache/old.ndx"));
  586.       
  587.       rename(fconcat(opt->path_log,"hts-cache/new.dat"),fconcat(opt->path_log,"hts-cache/old.dat"));
  588.       rename(fconcat(opt->path_log,"hts-cache/new.ndx"),fconcat(opt->path_log,"hts-cache/old.ndx"));
  589.     } else {  // un des deux (ou les deux) fichiers cache absents: effacer l'autre Θventuel
  590. #if DEBUGCA
  591.       printf("new cache\n");
  592. #endif
  593.       if (fexist(fconcat(opt->path_log,"hts-cache/new.dat")))
  594.         remove(fconcat(opt->path_log,"hts-cache/new.dat"));
  595.       if (fexist(fconcat(opt->path_log,"hts-cache/new.ndx")))
  596.         remove(fconcat(opt->path_log,"hts-cache/new.ndx"));
  597.     }
  598.     
  599.     // charger index cache prΘcΘdent
  600.     if ((fexist(fconcat(opt->path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))) {  // cache prΘcΘdent
  601.       if ((fsize(fconcat(opt->path_log,"hts-cache/old.dat"))>=0) && (fsize(fconcat(opt->path_log,"hts-cache/old.ndx"))>0)) {
  602.         FILE* oldndx=NULL;
  603. #if DEBUGCA
  604.         printf("..load cache\n");
  605. #endif
  606.         cache->olddat=fopen(fconcat(opt->path_log,"hts-cache/old.dat"),"rb");        
  607.         oldndx=fopen(fconcat(opt->path_log,"hts-cache/old.ndx"),"rb");        
  608.         // les deux doivent Ωtre ouvrables
  609.         if ((cache->olddat==NULL) && (oldndx!=NULL)) {
  610.           fclose(oldndx);
  611.           oldndx=NULL;
  612.         }
  613.         if ((cache->olddat!=NULL) && (oldndx==NULL)) {
  614.           fclose(cache->olddat);
  615.           cache->olddat=NULL;
  616.         }
  617.         // lire index
  618.         if (oldndx!=NULL) {
  619.           int buffl;
  620.           fclose(oldndx); oldndx=NULL;
  621.           // lire ndx, et lastmodified
  622.           buffl=fsize(fconcat(opt->path_log,"hts-cache/old.ndx"));
  623.           cache->use=readfile(fconcat(opt->path_log,"hts-cache/old.ndx"));
  624.           if (cache->use!=NULL) {
  625.             char firstline[256];
  626.             char* a=cache->use;
  627.             a+=cache_brstr(a,firstline);
  628.             if (strncmp(firstline,"CACHE-",6)==0) {       // Nouvelle version du cache
  629.               if (strncmp(firstline,"CACHE-1.",8)==0) {      // Version 1.1x
  630.                 cache->version=(int)(firstline[8]-'0');           // cache 1.x
  631.                 if (cache->version <= 2) {
  632.                   a+=cache_brstr(a,firstline);
  633.                   strcpy(cache->lastmodified,firstline);
  634.                 } else {
  635.                   if (opt->errlog) {
  636.                     fspc(opt->errlog,"error"); fprintf(opt->errlog,"Cache: version 1.%d not supported, ignoring current cache"LF,cache->version);
  637.                     fflush(opt->errlog);
  638.                   }
  639.                   fclose(cache->olddat);
  640.                   cache->olddat=NULL;
  641.                   freet(cache->use);
  642.                   cache->use=NULL;
  643.                 }
  644.               } else {        // non supportΘ
  645.                 if (opt->errlog) {
  646.                   fspc(opt->errlog,"error"); fprintf(opt->errlog,"Cache: %s not supported, ignoring current cache"LF,firstline);
  647.                   fflush(opt->errlog);
  648.                 }
  649.                 fclose(cache->olddat);
  650.                 cache->olddat=NULL;
  651.                 freet(cache->use);
  652.                 cache->use=NULL;
  653.               }
  654.               /* */
  655.             } else {              // Vieille version du cache
  656.               /* */
  657.               if (opt->log) {
  658.                 fspc(opt->log,"warning"); fprintf(opt->log,"Cache: importing old cache format"LF);
  659.                 fflush(opt->log);
  660.               }
  661.               cache->version=0;        // cache 1.0
  662.               strcpy(cache->lastmodified,firstline); 
  663.             }
  664.             opt->is_update=1;        // signaler comme update
  665.  
  666.             /* Create hash table for the cache (MUCH FASTER!) */
  667. #if HTS_FAST_CACHE
  668.             if (cache->use) {
  669.               char line[HTS_URLMAXSIZE*2];
  670.               char linepos[256];
  671.               int  pos;
  672.               while ( (a!=NULL) && (((int) a) < ((int)(cache->use+buffl))) ) {
  673.                 a=strchr(a+1,'\n');     /* start of line */
  674.                 if (a) {
  675.                   a++;
  676.                   /* read "host/file" */
  677.                   a+=binput(a,line,HTS_URLMAXSIZE);
  678.                   a+=binput(a,line+strlen(line),HTS_URLMAXSIZE);
  679.                   /* read position */
  680.                   a+=binput(a,linepos,200);
  681.                   sscanf(linepos,"%d",&pos);
  682.                   inthash_add((inthash)cache->hashtable,line,pos);
  683.                 }
  684.               }
  685.               /* Not needed anymore! */
  686.               freet(cache->use);
  687.               cache->use=NULL;
  688.             }
  689. #endif
  690.           }
  691.         }
  692.       }  // taille cache>0
  693.     }  // cache precedent existe
  694.     
  695. #if DEBUGCA
  696.     printf("..create cache\n");
  697. #endif
  698.     // ouvrir caches actuels
  699.     cache->dat=fopen(fconcat(opt->path_log,"hts-cache/new.dat"),"wb");        
  700.     cache->ndx=fopen(fconcat(opt->path_log,"hts-cache/new.ndx"),"wb");        
  701.     // les deux doivent Ωtre ouvrables
  702.     if ((cache->dat==NULL) && (cache->ndx!=NULL)) {
  703.       fclose(cache->ndx);
  704.       cache->ndx=NULL;
  705.     }
  706.     if ((cache->dat!=NULL) && (cache->ndx==NULL)) {
  707.       fclose(cache->dat);
  708.       cache->dat=NULL;
  709.     }
  710.     
  711.     if (cache->ndx!=NULL) {
  712.       char s[256];
  713.       
  714.       cache_wstr(cache->dat,"CACHE-1.2");
  715.       fflush(cache->dat);
  716.       cache_wstr(cache->ndx,"CACHE-1.2");
  717.       fflush(cache->ndx);
  718.       //
  719.       time_gmt_rfc822(s);   // date et heure actuelle GMT pour If-Modified-Since..
  720.       cache_wstr(cache->ndx,s);        
  721.       fflush(cache->ndx);    // un petit fflush au cas o∙
  722.       
  723.       // supprimer old.lst
  724.       if (fexist(fconcat(opt->path_log,"hts-cache/old.lst")))
  725.         remove(fconcat(opt->path_log,"hts-cache/old.lst"));
  726.       // renommer
  727.       if (fexist(fconcat(opt->path_log,"hts-cache/new.lst")))
  728.         rename(fconcat(opt->path_log,"hts-cache/new.lst"),fconcat(opt->path_log,"hts-cache/old.lst"));
  729.       // ouvrir
  730.       cache->lst=fopen(fconcat(opt->path_log,"hts-cache/new.lst"),"wb");
  731.       {
  732.         filecreate_params tmp;
  733.         strcpy(tmp.path,opt->path_html);    // chemin
  734.         tmp.lst=cache->lst;                 // fichier lst
  735.         filenote("",&tmp);        // initialiser filecreate
  736.       }
  737.  
  738.       // test
  739.       // cache_writedata(cache->ndx,cache->dat,"//[TEST]//","test1","TEST PIPO",9);
  740.     }
  741.     
  742.   }
  743.   
  744. }
  745.   
  746.   
  747.   
  748.  
  749. // lire un fichier.. (compatible \0)
  750. char* readfile(char* fil) {
  751.   char* adr=NULL;
  752.   int len=0;
  753.   len=fsize(fil);
  754.   if (len>0) {  // existe
  755.     FILE* fp;
  756.     fp=fopen(fconv(fil),"rb");
  757.     if (fp!=NULL) {  // n'existe pas (!)
  758.       adr=(char*) malloct(len+1);
  759.       if (adr!=NULL) {
  760.         if ((int) fread(adr,1,len,fp)!=len) {    // fichier endommagΘ ?
  761.           freet(adr);
  762.           adr=NULL;
  763.         } else
  764.           *(adr+len)='\0';
  765.       }
  766.       fclose(fp);
  767.     }
  768.   }
  769.   return adr;
  770. }
  771.  
  772. char* readfile_or(char* fil,char* defaultdata) {
  773.   char* realfile=fil;
  774.   char* ret;
  775.   if (!fexist(fil))
  776.     realfile=fconcat(hts_rootdir(NULL),fil);
  777.   ret=readfile(realfile);
  778.   if (ret)
  779.     return ret;
  780.   else {
  781.     char *adr=malloct(strlen(defaultdata)+2);
  782.     if (adr) {
  783.       strcpy(adr,defaultdata);
  784.       return adr;
  785.     }
  786.   }
  787.   return NULL;
  788. }
  789.  
  790. // Θcriture/lecture d'une chaεne sur un fichier
  791. // -1 : erreur, sinon 0
  792. int cache_wstr(FILE* fp,char* s) {
  793.   int i;
  794.   char buff[256];
  795.   i=strlen(s);
  796.   sprintf(buff,"%d\n",i);
  797.   if (fwrite(buff,1,strlen(buff),fp) != strlen(buff))
  798.     return -1;
  799.   if (i>0)
  800.   if ((int) fwrite(s,1,i,fp) != i)
  801.     return -1;
  802.   return 0;
  803. }
  804. void cache_rstr(FILE* fp,char* s) {
  805.   int i;
  806.   char buff[256];
  807.   linput(fp,buff,256);
  808.   sscanf(buff,"%d",&i);
  809.   if (i>0)
  810.     fread(s,1,i,fp);
  811.   *(s+i)='\0';
  812. }
  813. int cache_brstr(char* adr,char* s) {
  814.   int i;
  815.   int off;
  816.   char buff[256];
  817.   off=binput(adr,buff,256);
  818.   adr+=off;
  819.   sscanf(buff,"%d",&i);
  820.   if (i>0)
  821.     strncpy(s,adr,i);
  822.   *(s+i)='\0';
  823.   off+=i;
  824.   return off;
  825. }
  826. int cache_quickbrstr(char* adr,char* s) {
  827.   int i;
  828.   int off;
  829.   char buff[256];
  830.   off=binput(adr,buff,256);
  831.   adr+=off;
  832.   sscanf(buff,"%d",&i);
  833.   if (i>0)
  834.     strncpy(s,adr,i);
  835.   *(s+i)='\0';
  836.   off+=i;
  837.   return off;
  838. }
  839. /* idem, mais en int */
  840. int cache_brint(char* adr,int* i) {
  841.   char s[256];
  842.   int r=cache_brstr(adr,s);
  843.   if (r!=-1)
  844.     sscanf(s,"%d",i);
  845.   return r;
  846. }
  847. void cache_rint(FILE* fp,int* i) {
  848.   char s[256];
  849.   cache_rstr(fp,s);
  850.   sscanf(s,"%d",i);
  851. }
  852. int cache_wint(FILE* fp,int i) {
  853.   char s[256];
  854.   sprintf(s,"%d",(int) i);
  855.   return cache_wstr(fp,s);
  856. }
  857. void cache_rLLint(FILE* fp,LLint* i) {
  858.   char s[256];
  859.   cache_rstr(fp,s);
  860.   sscanf(s,LLintP,i);
  861. }
  862. int cache_wLLint(FILE* fp,LLint i) {
  863.   char s[256];
  864.   sprintf(s,LLintP,(LLint) i);
  865.   return cache_wstr(fp,s);
  866. }
  867. // -- cache --
  868.